package com.juhuixing.user.server.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.juhuixing.user.server.business.service.UserService;
import com.juhuixing.user.server.persistence.entity.BaseUser;
import com.juhuixing.common.assembly.redis.RedisServiceUtil;
import com.juhuixing.common.assembly.redis.SnowflakeIdWorker;
import com.juhuixing.common.assembly.redis.config.RedisConstant;
import com.juhuixing.common.assembly.redis.config.RedisKey;
import com.juhuixing.common.base.ResponseCode;
import com.juhuixing.common.config.service.impl.BaseServiceImpl;
import com.juhuixing.common.constant.AuthConstant;
import com.juhuixing.common.constant.KafkaTopicNameConst;
import com.juhuixing.common.dto.BaseUserDTO;
import com.juhuixing.common.dto.UserDetailDTO;
import com.juhuixing.common.enums.BaseEnum;
import com.juhuixing.common.model.TokenData;
import com.juhuixing.common.utils.SmsUtil;
import com.juhuixing.common.utils.custom.BeanUtil;
import com.juhuixing.common.utils.date.ConstellationUtil;
import com.juhuixing.common.utils.encryption.BCryptPasswordUtil;
import com.juhuixing.user.server.feign.AuthService;
import com.juhuixing.user.server.persistence.entity.WxUserInfo;
import com.juhuixing.user.server.persistence.mapper.BaseUserMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedHashMap;
import java.util.Objects;
import java.util.Random;

/**
 * 功能描述: 
 * @author: 刘猛
 * @date: 2019/2/20 16:44
 **/
@Slf4j
@Service
public class UserServiceImpl extends BaseServiceImpl<BaseUserMapper, BaseUser> implements UserService {

    @Autowired
    private AuthService authService;

    @Autowired(required = false)
    KafkaTemplate<?, String> kafkaTemplate;

    @Override
    public BaseUser findByUsername(String username) {
        return this.getOne(new QueryWrapper<BaseUser>().eq(BaseUser.USERNAME, username).eq(BaseUser.STATUS, BaseEnum.YES.getCode()));
    }

    @Override
    public String createSmsCode(String phone) {
        try {
            final String code = String.valueOf(new Random().nextInt(9000) + 1000);
//            SmsUtil.sendSms(ZooConstant.SIGN_NAME, ZooConstant.SMS_TEMPLATE_CODE, phone, code);
//            存入缓存
            RedisServiceUtil.set(new RedisKey(RedisConstant.VERIFICATION_CODE_PREFIX, phone).getRealKey(), code, 60);
            log.info("手机号:{}的登录/注册验证码:{}", phone, code);
            return code;
        } catch (Exception e) {
            log.error("手机号:{}的登录/注册验证码发送失败", phone);
            return null;
        }
    }

    @Override
    public TokenData phoneLogin(String phone, String smsCode,String source) {
        /**验证码错误**/
        TokenData data = checkSmsCode(phone,smsCode);
        if(Objects.nonNull(data)){
            return data;
        }
        /**1：检测用户是否已经注册过还是新用户**/
        BaseUser user = this.getOne(new QueryWrapper<BaseUser>().eq(BaseUser.PHONE,phone).eq(BaseUser.STATUS, BaseEnum.YES.getCode()));
        /**新用户**/
        if(Objects.isNull(user)){
            /**新用户注册**/
            user = new BaseUser();
            user.setUsername(SnowflakeIdWorker.generateId().toString());
            user.setPhone(phone);
            user.setPassword(BCryptPasswordUtil.getDefaultPwd(AuthConstant.CONST_PASS_CODE));
            user.setSource(source);
            this.save(user);
        }
        /**老用户的话直接去获取token**/
        data = getTokenData(user);
        /**并返回用户和IM信息**/
        data.setUser(BeanUtil.convert(user, BaseUserDTO.class));
        data.setIsCompleted(this.checkProfileIsCompleted(user));
        return data;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TokenData wechatLogin(String phone,String avatar,
                                 String nickName,String petNickname,
                                 Integer sex,String birthday,
                                 String openId,String unionId,
                                 String petImage,String backImage,
                                 String voiceIntro,String petVoice,
                                 Integer petType,String source,
                                 String wxavatar,String wxnickname,
                                 Integer gender,String province,String city
    ) {
        /**检测改手机号是否已经注册过**/
        BaseUser user = this.getOne(new QueryWrapper<BaseUser>().eq(BaseUser.PHONE,phone).eq(BaseUser.STATUS, BaseEnum.YES.getCode()));
        if(Objects.nonNull(user)){
            /**已经使用该手机注册过了 更新微信信息**/
            this.setUserValue(
                    avatar,
                    nickName,
                    petNickname,
                    sex,
                    birthday,
                    openId,
                    unionId,
                    petImage,
                    backImage,
                    voiceIntro,
                    petVoice,
                    petType,
                    source,
                    user
            );
            /**null值不会被更新**/
            this.updateById(user);
        }else{
            user = new BaseUser();
            user.setUsername(SnowflakeIdWorker.generateId().toString());
            user.setPhone(phone);
            user.setPassword(BCryptPasswordUtil.getDefaultPwd(AuthConstant.CONST_PASS_CODE));
            this.setUserValue(
                    avatar,
                    nickName,
                    petNickname,
                    sex,
                    birthday,
                    openId,
                    unionId,
                    petImage,
                    backImage,
                    voiceIntro,
                    petVoice,
                    petType,
                    source,
                    user
            );
            this.save(user);
        }

        /**单独保存微信用户信息**/
        kafkaTemplate.send(KafkaTopicNameConst.RECORD_WECHAT_INFO_TOPIC,JSON.toJSONString(
              new WxUserInfo(
                        user.getId()
                        ,unionId
                        ,openId
                        ,wxavatar
                        ,wxnickname
                        ,gender
                        ,province
                        ,city
                    )
            )
        );
        TokenData data = getTokenData(user);
        /**并返回用户和IM信息**/
        data.setUser(BeanUtil.convert(user, BaseUserDTO.class));
        return data;
    }

    private void setUserValue(String avatar, String nickName,
                              String petNickname,Integer sex,
                              String birthday, String openId,
                              String unionId, String petImage,
                              String backImage,String voiceIntro,
                              String petVoice,Integer petType,
                              String source,BaseUser user) {
        user.setAvatar(avatar);
        user.setNickname(nickName);
        user.setPetNickname(petNickname);
        user.setOpenId(openId);
        user.setUnionId(unionId);
        user.setSex(sex);
        user.setBirthday(birthday);
        if(StringUtils.isNotBlank(birthday)){
            user.setConstellation(ConstellationUtil.getConstellation(birthday));
        }
        user.setPetImage(petImage);
        user.setBackImage(backImage);
        user.setVoiceIntro(voiceIntro);
        user.setPetVoice(petVoice);
        user.setPetType(petType);
        user.setSource(source);
    }

    /**
     * 功能描述: 检测验证码是否错误
     * @methodName checkSmsCode
     * @author: 刘猛
     * @date: 2019/4/25 16:37
     * @param: [phone, smsCode]
     * @return: com.juhuixing.common.model.TokenData
     **/
    private TokenData checkSmsCode(String phone,String smsCode){
        TokenData token = null;
        String cachedCode = RedisServiceUtil.get(new RedisKey(RedisConstant.VERIFICATION_CODE_PREFIX, phone).getRealKey());
        /**验证码错误**/
        if(!StringUtils.equals(smsCode,cachedCode)){
            token = new TokenData();
            token.setCode(ResponseCode.SMS_CODE_ERR.getCode());
            token.setErrMsg(ResponseCode.SMS_CODE_ERR.getDesc());
        }
        return token;
    }

    /**
     * 功能描述:
     * @methodName 获取token
     * @author: 刘猛
     * @date: 2019/4/25 15:50
     * @param: [user]
     * @return: com.juhuixing.common.model.TokenData
     **/
    private TokenData getTokenData(BaseUser user) {
        LinkedHashMap tokenInfo = (LinkedHashMap) authService.authToken(AuthConstant.GRANT_TYPE, user.getUsername(), AuthConstant.CONST_PASS_CODE, AuthConstant.CLIENT_ID, AuthConstant.CLIENT_SECRET);
        TokenData token = Objects.nonNull(tokenInfo) ? BeanUtil.convert(tokenInfo, TokenData.class) : new TokenData();
        token.setCode(ResponseCode.SUCCESS_CODE.getCode());
        return token;
    }

    private Integer checkProfileIsCompleted(BaseUser user){
        return StringUtils.isNotBlank(user.getVoiceIntro()) && StringUtils.isNotBlank(user.getPetImage()) && StringUtils.isNotBlank(user.getPetNickname()) ? BaseEnum.YES.getCode() : BaseEnum.NO.getCode();
    }



    @Override
    public TokenData pwdLogin (String username, String password) {
        LinkedHashMap tokenInfo = (LinkedHashMap) authService.authToken(AuthConstant.GRANT_TYPE,username, password, AuthConstant.CLIENT_ID, AuthConstant.CLIENT_SECRET);
        TokenData token = Objects.nonNull(tokenInfo) ? BeanUtil.convert(tokenInfo, TokenData.class) : new TokenData();
        token.setCode(ResponseCode.SUCCESS_CODE.getCode());
        BaseUser user = this.findByUsername(username);
        token.setUser(BeanUtil.convert(user,BaseUserDTO.class));
        token.setIsCompleted(this.checkProfileIsCompleted(user));
        return token;
    }


    @Override
    public UserDetailDTO getUserDetail(String currentUserName) {
        return null;
    }
}
